package com.yunxin.common.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author zero°
 * @since 2023-06-05
 */
@Slf4j
public enum OkHttpUtils {

    /**
     * 单例
     */
    X;

    private final ConnectionPool connectionPool = new ConnectionPool();
    private final OkHttpClient client = new OkHttpClient.Builder().
            connectTimeout( 10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .connectionPool(connectionPool)
            .build();
    private final MediaType mediaType = MediaType.parse("application/json;charset=UTF-8");

    private void setHeaders(Request.Builder builder, Map<String, String> headers){
        if (null != headers && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                builder.header(entry.getKey(), entry.getValue());
            }
        }
    }

    public String post(String url, String json) {
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.post(RequestBody.create(json, mediaType));
        //setHeaders(builder, headers);
        Request request = builder.build();
        Call call = client.newCall(request);
        try( Response execute = call.execute()) {
            String string = Objects.requireNonNull(execute.body()).string();
            log.info("外部接口请求：url:{},request:{},response:{}", url, json, string);
            return string;
        } catch (IOException e) {
            log.error("执行POST请求异常,url:{},参数:{}", url, json, e);
            throw new IllegalStateException(e);
        }
    }

    public String post(String url, String json, Map<String, String> headers) {
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.post(RequestBody.create(json, mediaType));
        setHeaders(builder, headers);
        Request request = builder.build();
        Call call = client.newCall(request);
        try( Response execute = call.execute()) {
            String string = Objects.requireNonNull(execute.body()).string();
            log.info("外部接口请求：url:{},request:{},response:{}", url, json, string);
            return string;
        } catch (IOException e) {
            log.error("执行POST请求异常,url:{},参数:{}", url, json, e);
            throw new IllegalStateException(e);
        }
    }

    public <T> T postByFormData(String url, MultipartBody requestBody, com.fasterxml.jackson.core.type.TypeReference<T> typeReference){
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.post(requestBody);
        Request request = builder.build();
        Call call = client.newCall(request);
        try(Response execute = call.execute()) {
            String string = Objects.requireNonNull(execute.body()).string();
            log.info("外部接口请求：url:{},request:{},response:{}", url, JacksonUtils.X.format(requestBody), string);
            return JacksonUtils.X.parse(string, typeReference);
        } catch (IOException e) {
            log.error("执行POST请求异常,url:{},参数:{}", url, JacksonUtils.X.format(requestBody), e);
            throw new IllegalStateException(e);
        }
    }

    public String get(String url ){
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.get();
        //setHeaders(builder, headers);
        Request request = builder.build();
        Call call = client.newCall(request);
        try {
            Response execute = call.execute();
            String string = Objects.requireNonNull(execute.body()).string();
            log.info("外部接口请求：url:{},response:{}", url, string);
            return string;
        } catch (IOException e) {
            log.error("执行get请求异常,url:{}", url, e);
            throw new IllegalStateException(e);
        }
    }


    public String get(String url, Map<String, String> headers) {
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.get();
        setHeaders(builder, headers);
        Request request = builder.build();
        Call call = client.newCall(request);
        try {
            Response execute = call.execute();
            String string = Objects.requireNonNull(execute.body()).string();
            log.info("外部接口请求：url:{},response:{}", url, string);
            return string;
        } catch (IOException e) {
            log.error("执行get请求异常,url:{}", url, e);
            throw new IllegalStateException(e);
        }
    }

    public <T> T get(String url, Class<T> clazz, Map<String, String> headers) {
        String content = get(url, headers);
        return JacksonUtils.X.parse(content, clazz);
    }


    public <T> T get(String url,  com.fasterxml.jackson.core.type.TypeReference<T> typeReference, Map<String, String> headers) {
        String content = get(url, headers);
        return JacksonUtils.X.parse(content, typeReference);
    }


    public <T> T post(String url, Object object, Class<T> clazz) {
        return post(url, JacksonUtils.X.format(object), clazz, Collections.emptyMap());
    }

    public <T> T post(String url, Object object, Class<T> clazz, Map<String, String> headers) {
        return post(url, JacksonUtils.X.format(object), clazz, headers);
    }

    public <T> T post(String url, Object object, com.fasterxml.jackson.core.type.TypeReference<T> typeReference) {
        return post(url, JacksonUtils.X.format(object), typeReference, Collections.emptyMap());
    }

    public <T> T post(String url, Object object, com.fasterxml.jackson.core.type.TypeReference<T> typeReference, Map<String, String> headers) {
        return post(url, JacksonUtils.X.format(object), typeReference, headers);
    }

    public <T> T post(String url, String json, Class<T> clazz, Map<String, String> headers) {
        String content = post(url, json, headers);
        return JacksonUtils.X.parse(content, clazz);
    }

    public <T> T post(String url, String json, TypeReference<T> typeReference, Map<String, String> headers) {
        String content = post(url, json, headers);
        return JacksonUtils.X.parse(content, typeReference);
    }

}
